package certificate



type Subject struct{
        CommonName:   string,   // 核心：域名/IP
        Organization: []strin , // 组织名称（自定义）
        Country:      []string ,      // 国家代码（ISO 3166双字母）
        Province:     []string ,// 省份（自定义）
        Locality:     []string , // 城市（自定义）
    }



// 证书参数
type CertParams struct {
    CommonName   string   // 证书通用名称（域名/IP）
    KeySize      int      // 密钥长度（2048/4096）
    ValidityDays int      // 有效期（天）
    OutCert      string   // 证书输出路径
    OutKey       string   // 私钥输出路径
    SANs         []string //  SubjectAlternativeName（多域名/IP）
    EncryptKey   bool     // 是否加密私钥
    Password     string   // 私钥加密密码（EncryptKey=true时必填）
}



// 构建X.509证书模板
func buildCertificateTemplate(params CertParams) (*x509.Certificate, error) {
    // 1. 生成唯一的证书序列号（避免重复，实际场景建议用随机数）
    serialNumber, err := rand.Int(rand.Reader, big.NewInt(1000000000000000000))
    if err != nil {
        return nil, fmt.Errorf("生成序列号失败：%v", err)
    }

    // 2. 构建证书主体信息（Subject）
    subject := pkix.Name{
        CommonName:   params.CommonName,   // 核心：域名/IP
        Organization: []string{"Self-Signed CA"}, // 组织名称（自定义）
        Country:      []string{"CN"},      // 国家代码（ISO 3166双字母）
        Province:     []string{"Guangdong"},// 省份（自定义）
        Locality:     []string{"Shenzhen"}, // 城市（自定义）
    }

    // 3. 构建SubjectAlternativeName（SAN）
    generalNames := make(pkix.GeneralNames, 0, len(params.SANs))
    for _, san := range params.SANs {
        // 判断是域名还是IP
        if ip := net.ParseIP(san); ip != nil {
            // 是IP地址
            generalNames = append(generalNames, pkix.GeneralName{
                Type: 2, // 2=IP地址类型
                Value: ip,
            })
        } else {
            // 是域名
            generalNames = append(generalNames, pkix.GeneralName{
                Type: 2DNSName, // 2DNSName=域名类型
                Value: san,
            })
        }
    }

    // 4. 证书模板核心配置
    return &x509.Certificate{
        SerialNumber: serialNumber,
        Subject:      subject,
        Issuer:       subject, // 自签名：签发者=主体
        NotBefore:    time.Now().Add(-1 * time.Hour), // 提前1小时生效（避免时区问题）
        NotAfter:     time.Now().Add(time.Duration(params.ValidityDays) * 24 * time.Hour),
        // 密钥用途：支持加密、签名、CA签发
        KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
        // 扩展用途：支持服务器和客户端认证（双向TLS）
        ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
        // SAN：解决CN单域名限制
        SubjectAlternativeName: generalNames,
        BasicConstraintsValid:  true,
        IsCA:                   true, // 标记为CA证书（可签发子证书）
        MaxPathLen:             0,    // 路径长度：0=仅允许直接签发终端证书
    }, nil
}



// 保存PEM格式文件
func savePEMFile(filename, blockType string, data []byte) error {
    // 创建父目录（若不存在）
    if err := os.MkdirAll(getDir(filename), 0755); err != nil {
        return fmt.Errorf("创建父目录失败：%v", err)
    }

    // 创建文件（权限0644：所有者读写，其他只读）
    file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
    if err != nil {
        return fmt.Errorf("创建文件失败：%v", err)
    }
    defer file.Close()

    // 编码PEM格式并写入文件
    if err := pem.Encode(file, &pem.Block{
        Type:  blockType,
        Bytes: data,
    }); err != nil {
        return fmt.Errorf("编码PEM失败：%v", err)
    }
    return nil
}


func CreateCertificate2() {
    // 为CA生成RSA密钥
    caPriv, _ := rsa.GenerateKey(rand.Reader, 2048)
    caPub := &caPriv.PublicKey

    // 创建CA证书模板
    ca := &x509.Certificate{
        // ...填入上面提到的字段...
    }

    // 创建CA证书
    caBytes, _ := x509.CreateCertificate(rand.Reader, ca, ca, caPub, caPriv)

    // 为用户证书生成RSA密钥
    userPriv, _ := rsa.GenerateKey(rand.Reader, 2048)
    userPub := &userPriv.PublicKey

    // 创建用户证书模板
    user := &x509.Certificate{
        // ...填入相应字段，但不是CA...
    }

    // 使用CA证书和私钥签发用户证书
    userBytes, _ := x509.CreateCertificate(rand.Reader, user, ca, userPub, caPriv)

    // 这里caBytes和userBytes就是PEM编码的证书
    // 可以将它们写入文件或进行其他处理
}